/***************************************************************************************************
 *Copyright(C),2010-2017,Sumscope
 *FileName	:  proto_message.h
 *Author	:  scofined.qi
 *Version	:  1.0
 *Date		:  2019/01/18
 *Desc		:  //用于主要说明此程序文件完成的主要功能
 *Relation :
 *Others	:  //其他内容说明
 *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
 *History	:
 * //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
 ***************************************************************************************************/
#ifndef PROTO_MESSAGE_H_52A7DC9B_41D0_4345_BDD3_1A7DD97D9C24
#define PROTO_MESSAGE_H_52A7DC9B_41D0_4345_BDD3_1A7DD97D9C24
#include <string>
#include <vector>

#include "core/strings/BaseString.h"
#include "extdef.h"

#pragma warning(disable : 4251)

namespace qb {
namespace base {
namespace msg {
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef short int16_t;
typedef unsigned int uint32_t;
typedef int int32_t;
typedef unsigned long long uint64_t;
typedef long long int64_t;

struct Buffer {
  const char* data;  // 该buffer的起始地址
  int size;          // 该buffer的内存大小
  int count;         // 用于检查,该buffer里面有几个值
 public:
  Buffer() : data(nullptr), size(0), count(0) {}
  Buffer(const Buffer& buf)
      : data(buf.data), size(buf.size), count(buf.count) {}
  Buffer(const char* d, int s) : data(d), size(s), count(0) {}
  Buffer(const char* d, int s, int c) : data(d), size(s), count(c) {}
  Buffer& operator=(const Buffer& buf) {
    data = buf.data;
    size = buf.size;
    count = buf.count;
    return *this;
  }
  bool operator!=(const Buffer& buf) const {
    return data != buf.data || size != buf.size || count != buf.count;
  }
  bool operator==(const Buffer& buf) const {
    return data == buf.data && size == buf.size && count == buf.count;
  }
  const char* end() const { return data + size; }
};
class Raw {
 public:
  const void* Data;
  uint32_t Length;

  Raw() : Data(nullptr), Length(0) {}
  Raw(const Raw& raw) : Data(raw.Data), Length(raw.Length) {}
  Raw(const char* d, int len) : Data(d), Length(len) {}
  ~Raw() {}

  bool Copy(const Raw& raw);
  bool Copy(const void* buffer, size_t buflen);

  void Ref(const Raw& raw);
  void Clear();

  Raw& operator=(const Raw& raw) {
    Data = raw.Data;
    Length = raw.Length;
    return *this;
  }
  inline bool Owned() const { return owned_; }

 private:
  bool owned_;  // 是否由这个类自动释放。
};
class Message;
class SSPROTOAPI Value {
 public:
  enum VarType : uint8_t {  // 注意:此字段内容必须与ss::proto::Variant里的定义值一致

    VAR_UNKNOWN = 0,
    VAR_VOID = VAR_UNKNOWN,

    VAR_BOOL = 1,

    VAR_INT8 = 2,
    VAR_UINT8 = 3,

    VAR_INT16 = 4,
    VAR_UINT16 = 5,
    VAR_INT32 = 6,
    VAR_UINT32 = 7,
    VAR_INT64 = 8,
    VAR_UINT64 = 9,

    VAR_FLOAT = 10,
    VAR_DOUBLE = 11,

    VAR_STRING = 12,  // str16
    VAR_RAW = 13,     // vbin32

    VAR_MAP = 14,  // map
    VAR_LIST = 15  // list
  };

 public:           // 设计为40字节一个节点
  Message* msg;    // 指向其拥有者Message的指针
  uint8_t Type;    // 当前节点类型,适配,ss::proto::Variant::VarType值
  uint8_t ptype;   // 父亲节点类型,可能为空,list,map
  uint8_t keylen;  // 当父节点为map时,指key的长度,没有0结尾
  uint8_t level;   // 用于调试,0表示顶级节点
  int bytes;       // 该值占据的总字节大小
  int size;        // 该值的实际内容编码长度,排除type,tag,len,count
  int count;       // 子节点个数,只有当list/map,此值才可能不为0
  const char* key;  // 当ptype为map的时候,此值表示对应的key
  const char* data;  // 该值的实际指针,保证从data到data+size是有效的
  Buffer parent;     // 父亲节点的内容区
 public:
  Value()
      : msg(nullptr),
        Type(0),
        level(0),
        ptype(0),
        keylen(0),
        bytes(0),
        size(0),
        count(0),
        key(nullptr),
        data(nullptr) {}
  bool operator!=(const Value& v) const {
    return msg != v.msg || data != v.data || Type != v.Type || size != v.size;
  }
  const char* start() const { return data - (bytes - size); }
  const char* next() const { return data + size; }
  std::string tostring() const;  // 仅供调试用
  std::string GetKey() const {
    return key ? std::string(key, keylen) : std::string("");
  }
  std::string GetString() const;
  bool GetInt32(int& value) const;
  bool GetDouble(double& value) const;
  bool RefString(const char*& value, size_t& size) const;

#define DECLEAR_OPERATOR(TYPE) operator TYPE() const;
  DECLEAR_OPERATOR(bool);
  DECLEAR_OPERATOR(uint8_t);
  DECLEAR_OPERATOR(uint16_t);
  DECLEAR_OPERATOR(uint32_t);
  DECLEAR_OPERATOR(uint64_t);
  DECLEAR_OPERATOR(int8_t);
  DECLEAR_OPERATOR(int16_t);
  DECLEAR_OPERATOR(int32_t);
  DECLEAR_OPERATOR(int64_t);
  DECLEAR_OPERATOR(float);
  DECLEAR_OPERATOR(double);
};
class SSPROTOAPI ValueDict {
  typedef unsigned int uint;
  typedef unsigned short ushort;
  /*
  QB收到的字典数据包中的数据类型编码,目前只用到int32,string,double,time32四种类型
  */
 public:
  enum kPackDateType {
    kPackDateTypeNone = 0,
    kPackDateTypeInt8 = 1,
    kPackDateTypeUInt8 = 2,
    kPackDateTypeInt16 = 3,
    kPackDateTypeUInt16 = 4,
    kPackDateTypeInt32 = 5,
    kPackDateTypeUint32 = 6,
    kPackDateTypeInt64 = 7,
    kPackDateTypeUInt64 = 8,
    kPackDateTypeBool = 9,
    kPackDateTypeString = 10,
    kPackDateTypeFloat = 11,
    kPackDateTypeDouble = 12,
    kPackDateTypeRaw = 13,
    kPackDateTypeTime32 = 14,  // 等同于time_t，精度秒
    kPackDateTypeTime64 = 15,  // 等同于time_t + 毫秒，精度毫秒
    kPackDateTypeCount = 16
  };
  struct Field {
    kPackDateType type;
    int len;
    int col, row;
    const char* data;
    const char* name;
  };

 protected:
  struct PackHeader {   // 更新包中的数据头部
    uint tag;           // 文件开头的4个字节,0x44425253
    uint StartPos;      // 记录开始的偏移量
    uint RecordCount;   // 记录个数
    ushort FieldCount;  // 每条记录的字段个数
  };
  std::vector<const char*> m_fields;
  std::vector<Field> m_values;
  PackHeader m_head;
  char* m_buffer;
  int m_capcity;
  int m_packsize;  // 解压后的大小
 public:
  ValueDict();
  ~ValueDict();
  bool Parse(const char* data, int len);
  int GetRowCount() const { return m_head.RecordCount; }
  int GetColCount() const { return m_head.FieldCount; }
  bool GetValue(int row, int col, Field& value) const;
  const char* GetColName(int col) const;
  int GetSize() const { return m_packsize; }
  const char* GetBuffer() const { return m_buffer; }

 protected:
  bool IsValidDict(const PackHeader& head, const char* start, int nfield);
};
class SSPROTOAPI ValueList {
 public:
  class SSPROTOAPI const_iterator {
   protected:
    Buffer m_scope;  // 当前枚举器的范围
    Value m_value;   // 当前枚举到的值
    int m_index;     // 当前枚举器位于m_scope的第几个
   public:
   public:
    const_iterator() : m_index(-1) {}
    const_iterator(const Buffer& buf, const Value& v, int i)
        : m_scope(buf), m_value(v), m_index(0) {}
    inline int index() const { return m_index; }
    inline int size() const { return m_scope.count; }
    const_iterator& operator=(const const_iterator& iter) {
      m_scope = iter.m_scope;
      m_value = iter.m_value;
      m_index = iter.m_index;
      return *this;
    }
    const_iterator(const const_iterator& iter) {
      m_scope = iter.m_scope;
      m_value = iter.m_value;
      m_index = iter.m_index;
    }
    inline const Value* operator->() const { return &m_value; }
    inline bool operator!=(const const_iterator& iter) const {
      return m_index != iter.m_index || m_scope != iter.m_scope ||
             m_value != iter.m_value;
    }
    inline const Value& operator*() const { return m_value; }
    const const_iterator& operator++();
  };

 protected:
  Value m_value;
  const_iterator m_end;

 public:
  ValueList() {}
  ValueList(const Value& v) : m_value(v) {}
  const Value& value() const { return m_value; }
  int size() const { return m_value.count; }
  const_iterator begin() const;
  const const_iterator& end() const { return m_end; }
  void print(int level = 0) const;
  operator const Value&() const { return m_value; }
};

class SSPROTOAPI ValueMap : public ValueList {
 public:
  ValueMap(const Value& v) : ValueList(v) {}
  ValueMap() {}
  bool find(const char* name, Value& v) const;

#define VALUEMAP_GET(NAME, VAL) \
  {                             \
    Value v;                    \
    if (find(NAME, v)) {        \
      VAL = v;                  \
      return true;              \
    }                           \
    return false;               \
  }
  bool GetBool(const char* name, bool& value) const {
    VALUEMAP_GET(name, value);
  }
  bool GetUInt8(const char* name, uint8_t& value) const {
    VALUEMAP_GET(name, value);
  }
  bool GetUInt16(const char* name, uint16_t& value) const {
    VALUEMAP_GET(name, value);
  }
  bool GetUInt32(const char* name, uint32_t& value) const {
    VALUEMAP_GET(name, value);
  }
  bool GetUInt64(const char* name, uint64_t& value) const {
    VALUEMAP_GET(name, value);
  }
  bool GetInt8(const char* name, int8_t& value) const {
    VALUEMAP_GET(name, value);
  }
  bool GetInt16(const char* name, int16_t& value) const {
    VALUEMAP_GET(name, value);
  }
  bool GetInt32(const char* name, int32_t& value) const {
    VALUEMAP_GET(name, value);
  }
  bool GetInt64(const char* name, int64_t& value) const {
    VALUEMAP_GET(name, value);
  }
  bool GetFloat(const char* name, float& value) const {
    VALUEMAP_GET(name, value);
  }
  bool GetDouble(const char* name, double& value) const {
    VALUEMAP_GET(name, value);
  }
  bool GetString(const char* name, const char*& value, size_t& size) const;
  bool GetMap(const char* name, ValueMap& vmap) const;
  bool GetList(const char* name, ValueList& vlist) const;
  bool GetRaw(const char* name, Raw& value) const;
};
#pragma warning(push)
#pragma warning(disable : 4251)
class FieldTable {
 public:
  enum kFindType {
    kFindTypeFail = 0,
    kFindTypeByOrder = 1,
    kFindTypeByBinary = 2
  };
  enum { kMaxFieldCount = 64 };  // 当一个map下面的字段小于64个,那么使用栈内存
  typedef Buffer Signature;
  typedef qb::base::StackArray<Value, kMaxFieldCount> ValueArray;
  static int CompByKey(const void* p1, const void* p2);
  static int CompString(const char* s1, int len1, const char* s2, int len2);

 private:
  Signature m_signature;  // 绑定当前的哪一个ValueMap
  Value m_search;         // 当前二分法搜索的key
  ValueArray m_values;  // 栈/堆上放置的解析好的当前map的值数组
  int m_lastpos;  // 上一次搜索的位置,按照顺序获取,性能最佳
 public:
  FieldTable();
  void rebuild(const ValueMap& map);
  const Buffer& buffer() const { return m_signature; }
  bool getFieldValue(int index, Value& v) const;
  kFindType getFieldValue(const char* name, int len, Value& v) const;
  int size() const { return m_values.size(); }
};
#pragma warning(pop)
class SSPROTOAPI Message {
  friend class ValueMap;
  FieldTable m_field_table;  // 任何时候都有且只有一个字段表,需要的时候重建
  ValueMap m_header;  // 头部
  ValueMap m_map;     // body
  int m_bfind;        //
  int m_sfind;        //
 private:
  Message(const Message& msg) = delete;
  Message& operator=(const Message& msg) = delete;

 public:
  Message();
  ~Message();
  void Clear();
  int decode(const char* buf, int len);
  int decodeMap(const char* buf, int len, bool inMap);
  const ValueMap& MapValue() const { return m_map; }
  const ValueMap& Header() const { return m_header; }
  static bool DecodeValue(const Buffer& buf, bool inMap, Value& v,
                          bool skipType = false);

 public:
  bool GetBool(const char* name, bool& value) const {
    return m_map.GetBool(name, value);
  }
  bool GetUInt8(const char* name, uint8_t& value) const {
    return m_map.GetUInt8(name, value);
  }
  bool GetUInt16(const char* name, uint16_t& value) const {
    return m_map.GetUInt16(name, value);
  }
  bool GetUInt32(const char* name, uint32_t& value) const {
    return m_map.GetUInt32(name, value);
  }
  bool GetUInt64(const char* name, uint64_t& value) const {
    return m_map.GetUInt64(name, value);
  }
  bool GetInt8(const char* name, int8_t& value) const {
    return m_map.GetInt8(name, value);
  }
  bool GetInt16(const char* name, int16_t& value) const {
    return m_map.GetInt16(name, value);
  }
  bool GetInt32(const char* name, int32_t& value) const {
    return m_map.GetInt32(name, value);
  }
  bool GetInt64(const char* name, int64_t& value) const {
    return m_map.GetInt64(name, value);
  }
  bool GetFloat(const char* name, float& value) const {
    return m_map.GetFloat(name, value);
  }
  bool GetDouble(const char* name, double& value) const {
    return m_map.GetDouble(name, value);
  }

 public:  // debug
  void print() const;

 protected:
  bool find(const char* name, const ValueMap& map, Value& v);
};

class SSPROTOAPI ProtoList {
 public:
  friend class ProtoMap;
  friend class ProtoMessage;
  typedef ValueList::const_iterator const_iterator;

 private:
  ValueList m_list;

 private:
  ProtoList(const ProtoList& pm) = delete;
  ProtoList& operator=(const ProtoList& pm) = delete;
  void SetList(const Value& list) { m_list = list; }

 public:
  ProtoList() {}
  ProtoList(const Value& v) : m_list(v) {}
  const_iterator begin() const { return m_list.begin(); }
  const_iterator end() const { return m_list.end(); }
  int size() const { return m_list.size(); }
  void clear() { m_list = ValueList(); }
  const ValueList& value() const { return m_list; }
};
class SSPROTOAPI ProtoMap {
 public:
  friend class ProtoMessage;
  typedef ValueList::const_iterator const_iterator;

 private:
  ValueMap m_map;
  std::vector<ProtoList*> m_reflist;

 private:
  ProtoMap(const ProtoMap& pm) = delete;
  ProtoMap& operator=(const ProtoMap& pm) = delete;
  void SetMap(const Value& v) { m_map = v; }

 public:
  ProtoMap() {}
  ProtoMap(const Value& v) : m_map(v) {}
  ProtoMap(const ValueMap& vmap) : m_map(vmap) {}
  ~ProtoMap() {}
  const_iterator begin() const { return m_map.begin(); }
  const_iterator end() const { return m_map.end(); }
  bool RefList(const char* name, const ProtoList*& pList) const;
  bool RefMapFrom(const Message& msg, const char* name);
  bool GetList(const char* name, ProtoList& list) const;
  bool getList(const char* name, ProtoList& list) const {
    return GetList(name, list);
  }
  bool GetMap(const char* name, ProtoMap& map) const;
  bool RefString(const char* name, const char*& value, size_t& size) const;
  bool GetRaw(const char* name, Raw& value) const;
  operator const ValueMap&() const { return m_map; }

  bool GetBool(const char* name, bool& value) const {
    return m_map.GetBool(name, value);
  }
  bool GetUInt8(const char* name, uint8_t& value) const {
    return m_map.GetUInt8(name, value);
  }
  bool GetUInt16(const char* name, uint16_t& value) const {
    return m_map.GetUInt16(name, value);
  }
  bool GetUInt32(const char* name, uint32_t& value) const {
    return m_map.GetUInt32(name, value);
  }
  bool GetUInt64(const char* name, uint64_t& value) const {
    return m_map.GetUInt64(name, value);
  }
  bool GetInt8(const char* name, int8_t& value) const {
    return m_map.GetInt8(name, value);
  }
  bool GetInt16(const char* name, int16_t& value) const {
    return m_map.GetInt16(name, value);
  }
  bool GetInt32(const char* name, int32_t& value) const {
    return m_map.GetInt32(name, value);
  }
  bool GetInt64(const char* name, int64_t& value) const {
    return m_map.GetInt64(name, value);
  }
  bool GetFloat(const char* name, float& value) const {
    return m_map.GetFloat(name, value);
  }
  bool GetDouble(const char* name, double& value) const {
    return m_map.GetDouble(name, value);
  }

  inline bool getBool(const std::string& name, bool& value) const {
    return GetBool(name.c_str(), value);
  }
  inline bool getUint8(const std::string& name, uint8_t& value) const {
    return GetUInt8(name.c_str(), value);
  }
  inline bool getUint16(const std::string& name, uint16_t& value) const {
    return GetUInt16(name.c_str(), value);
  }
  inline bool getUint32(const std::string& name, uint32_t& value) const {
    return GetUInt32(name.c_str(), value);
  }
  inline bool getUint64(const std::string& name, uint64_t& value) const {
    return GetUInt64(name.c_str(), value);
  }
  inline bool getInt8(const std::string& name, int8_t& value) const {
    return GetInt8(name.c_str(), value);
  }
  inline bool getInt16(const std::string& name, int16_t& value) const {
    return GetInt16(name.c_str(), value);
  }
  inline bool getInt32(const std::string& name, int32_t& value) const {
    return GetInt32(name.c_str(), value);
  }
  inline bool getInt64(const std::string& name, int64_t& value) const {
    return GetInt64(name.c_str(), value);
  }
  inline bool getFloat(const std::string& name, float& value) const {
    return GetFloat(name.c_str(), value);
  }
  inline bool getDouble(const std::string& name, double& value) const {
    return GetDouble(name.c_str(), value);
  }
};
class IRawParser {
 public:
  enum kExpectType {
    kExpectTypeNull,    // 默认值
    kExpectTypeString,  // 字符串
    kExpectTypeDouble,  // 双精度浮点数
    kExpectTypeInt,     // 整数:变长无符号64位整数
    kExpectTypeMax
  };
  virtual bool Parse(const char* data, int length) = 0;
  virtual int GetRow() const = 0;
  virtual int GetCol() const = 0;
  virtual const char* GetColName(int col) const = 0;
  virtual kExpectType GetColType(int col) const = 0;
  virtual bool IsCellDefault(int row, int col) const = 0;
  virtual bool GetCellValue(int row, int col, double& value) = 0;
  virtual bool GetCellValue(int row, int col, int64_t& value) = 0;
  virtual bool GetCellValue(int row, int col, const char*& value, int& len) = 0;
};
class SSPROTOAPI ProtoMessage {
  Message m_msg;

 public:
  ProtoMessage();
  ProtoMessage(const ProtoMap& map);
  bool GetList(const char* name, ProtoList& list) const;
  const ValueMap& MapValue() const { return m_msg.MapValue(); }
  const ValueMap& HeadValue() const { return m_msg.Header(); }
  bool GetRaw(const char* name, Raw& value) const {
    return m_msg.MapValue().GetRaw(name, value);
  }
  int GetAllKeySize();
  int ToJson(std::string& str);
  int ToJson(std::string& str, IRawParser* rawParser);
  void Dump(int id);
#define PROTOMSG_GET(NAME, VAL, FUNC) return m_msg.MapValue().FUNC(NAME, VAL);
  bool getList(const char* name, ProtoList& list) const {
    ValueList v;
    if (m_msg.MapValue().GetList(name, v)) {
      list.SetList(v);
      return true;
    }
    return false;
  }
  bool GetMap(const char* name, ProtoMap& map) const {
    ValueMap v;
    if (m_msg.MapValue().GetMap(name, v)) {
      map.SetMap(v);
      return true;
    }
    return false;
  }
  bool RefString(const char* name, const char*& value, size_t& size) const {
    return m_msg.MapValue().GetString(name, value, size);
  }

  bool GetBool(const char* name, bool& value) const {
    PROTOMSG_GET(name, value, GetBool);
  }
  bool GetUInt8(const char* name, uint8_t& value) const {
    PROTOMSG_GET(name, value, GetUInt8);
  }
  bool GetUInt16(const char* name, uint16_t& value) const {
    PROTOMSG_GET(name, value, GetUInt16);
  }
  bool GetUInt32(const char* name, uint32_t& value) const {
    PROTOMSG_GET(name, value, GetUInt32);
  }
  bool GetUInt64(const char* name, uint64_t& value) const {
    PROTOMSG_GET(name, value, GetUInt64);
  }
  bool GetInt8(const char* name, int8_t& value) const {
    PROTOMSG_GET(name, value, GetInt8);
  }
  bool GetInt16(const char* name, int16_t& value) const {
    PROTOMSG_GET(name, value, GetInt16);
  }
  bool GetInt32(const char* name, int32_t& value) const {
    PROTOMSG_GET(name, value, GetInt32);
  }
  bool GetInt64(const char* name, int64_t& value) const {
    PROTOMSG_GET(name, value, GetInt64);
  }
  bool GetFloat(const char* name, float& value) const {
    PROTOMSG_GET(name, value, GetFloat);
  }
  bool GetDouble(const char* name, double& value) const {
    PROTOMSG_GET(name, value, GetDouble);
  }
  inline bool getBool(const std::string& name, bool& value) const {
    return GetBool(name.c_str(), value);
  }
  inline bool getUint8(const std::string& name, uint8_t& value) const {
    return GetUInt8(name.c_str(), value);
  }
  inline bool getUint16(const std::string& name, uint16_t& value) const {
    return GetUInt16(name.c_str(), value);
  }
  inline bool getUint32(const std::string& name, uint32_t& value) const {
    return GetUInt32(name.c_str(), value);
  }
  inline bool getUint64(const std::string& name, uint64_t& value) const {
    return GetUInt64(name.c_str(), value);
  }
  inline bool getInt8(const std::string& name, int8_t& value) const {
    return GetInt8(name.c_str(), value);
  }
  inline bool getInt16(const std::string& name, int16_t& value) const {
    return GetInt16(name.c_str(), value);
  }
  inline bool getInt32(const std::string& name, int32_t& value) const {
    return GetInt32(name.c_str(), value);
  }
  inline bool getInt64(const std::string& name, int64_t& value) const {
    return GetInt64(name.c_str(), value);
  }
  inline bool getFloat(const std::string& name, float& value) const {
    return GetFloat(name.c_str(), value);
  }
  inline bool getDouble(const std::string& name, double& value) const {
    return GetDouble(name.c_str(), value);
  }

  std::string GetType() const;
  std::string getType() const;
  std::string GetMessageID() const;
  std::string getMessageID() const;
  std::string GetSubject() const;
  std::string getSubject() const;
  void Clear();
  int decode(const char* buf, int len);
};
}  // namespace msg
}  // namespace base
}  // namespace qb

#endif
